(ns btree.macros
	(:require [btree.operations :refer :all])
)

(defmacro tree-page
	[page children parent]
	`{:keys [~@page] :children [~@children] :parent ~parent}
)

(defmacro tree-from-pageList ;tworzy drzewo z listy stron. np: (3 6) (1 2) (4 5) (7 8)
	[size pageList] 
	(defmacro tree-from-list-loop
		[ptree [firstPage & restPages] counter childrenCounter parentQueue finalNextId]
		(let [childrenCount (if (>= (inc childrenCounter) finalNextId) 0 (inc (count firstPage))), newChildrenCounter (+ childrenCounter childrenCount)]
			(if (= finalNextId (inc counter))
				`(assoc ~ptree ~counter (tree-page ~firstPage ~(range childrenCounter newChildrenCounter) ~(first parentQueue)))
				`(tree-from-list-loop
					(assoc ~ptree ~counter (tree-page ~firstPage ~(range childrenCounter newChildrenCounter) ~(first parentQueue)))
					~restPages
					~(inc counter)
					~newChildrenCounter
					~(concat (rest parentQueue) (repeat childrenCount counter))
					~finalNextId
				)
			)
		)
	)
	(let [maxId# (+ (count pageList) 1), tree# { :pageSize size :nextId maxId# :root 1 }]
		`(tree-from-list-loop ~tree# ~pageList 1 2 [nil] ~maxId#); 
	)
)			
			
(defmacro tree-from-valueList
	;"creates new BTree from given numbers."
	[size & args]

	(defmacro macro-add-list 
		[tree vals]
		(if (= (count vals) 1)
			`(tree-add ~tree ~(first vals))
			`(macro-add-list (tree-add ~tree ~(first vals)) ~(rest vals))
		)
	)
	
	(let [tree# {:pageSize size :root 1 :nextId 2 1 {:keys [] :children [] :parent nil}}]
		`(macro-add-list ~tree# ~(into [] args))
	)
)		

(defmacro tree-do
	[[firstOp secondOp & restOps]]
	(if (nil? restOps)
		`(~(first secondOp) ~firstOp ~@(rest secondOp))
		`(tree-do ((~(first secondOp) ~firstOp ~@(rest secondOp)) ~@restOps))
	)
)	
